www.gusucode.com > VC++ 仿QQ多用户聊天程序-源码程序 > VC++ 仿QQ多用户聊天程序-源码程序/code/Server/ServerDlg.cpp
// ServerDlg.cpp : implementation file // download by http://www.NewXing.com #include "stdafx.h" #include "Server.h" #include "ServerDlg.h" #include "ClientSocket.h" #include "ListenSocket.h" #include "ServerAddressDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CServerDlg dialog CServerDlg::CServerDlg(CWnd* pParent /*=NULL*/) : CDialog(CServerDlg::IDD, pParent) { //{{AFX_DATA_INIT(CServerDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_pListenSocket = NULL; //监听套接字 m_pImageList = NULL; //图标列表 } void CServerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServerDlg) DDX_Control(pDX, IDC_CLIENT_LIST, m_ctlUserList); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CServerDlg, CDialog) //{{AFX_MSG_MAP(CServerDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_DESTROY() ON_NOTIFY(NM_RCLICK, IDC_CLIENT_LIST, OnRclickClientList) ON_COMMAND(ID_SERVER_LIST_DELETE_MENUITEM, OnServerListDeleteMenuitem) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CServerDlg message handlers BOOL CServerDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon //初始化 Init(); return TRUE; } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CServerDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CServerDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } CServerDlg::~CServerDlg() { } /* * 接受客户端连接请求 */ void CServerDlg::ProcessPendingAccept(void) { CClientSocket *pClient = new CClientSocket(this);//创建实例 SOCKADDR_IN clientAddr; int socketLen = sizeof(SOCKADDR_IN); m_pListenSocket->Accept(*pClient,(SOCKADDR*)&clientAddr, &socketLen);//接受客户端的连接 pClient->Init(); //初始化 pClient->SaveUserInfo(clientAddr); //保存用户的地址 m_csChatterList.Lock(); m_ChatterList.AddTail(pClient); //加入在线用户链表 m_csChatterList.Unlock(); } /* * 初始化 */ BOOL CServerDlg::Init(void) { InitListCtrlSetting(); //定义列表控件 InitUserList(); //初始化用户列表 LoadOfflineMsg(m_OfflineMsgList); //读取离线消息 return TRUE; } /* * 启动服务 */ BOOL CServerDlg::StartService(void) { CServerAddressDlg servAddrDlg; //服务器地址和端口对话框 if (IDOK != servAddrDlg.DoModal()) { return FALSE; } //获取服务器地址 in_addr servAdd; servAdd.S_un.S_addr = htonl(servAddrDlg.m_strServIP); //主机字节转换为网络字节 CString strServIP = inet_ntoa(servAdd); //转换为点格式 //创建CListenSocket对象 m_pListenSocket = new CListenSocket(this); //创建套接字 if (m_pListenSocket->Create(servAddrDlg.m_shServPort, SOCK_STREAM,strServIP)) { //开始监听 if (!m_pListenSocket->Listen()) { delete m_pListenSocket; m_pListenSocket = NULL; AfxMessageBox(_T("创建套接字失败!")); return FALSE; } }else { delete m_pListenSocket; m_pListenSocket = NULL; AfxMessageBox(_T("创建套接字失败!")); return FALSE; } return TRUE; } /* * 定义列表控件 */ void CServerDlg::InitListCtrlSetting(void) { m_pImageList = new CImageList(); ASSERT(m_pImageList != NULL); //32*32,8位,初始化为2个图标,每次增长2个图标 m_pImageList->Create(32, 32, ILC_COLOR8|ILC_MASK, 2, 2); CWinApp* pApp = AfxGetApp(); //获得应用程序指针 HICON hIconOnline = pApp->LoadIcon(IDI_CHATTER_ONLINE); //在线图标 HICON hIconOffline = pApp->LoadIcon(IDI_CHATTER_OFFLINE); //离线图标 m_pImageList->Add(hIconOnline); //加入图标 m_pImageList->Add(hIconOffline); //加入图标 //将图标列表赋值给列表控件 m_ctlUserList.SetImageList(m_pImageList, LVSIL_SMALL); //设置列表头 m_ctlUserList.InsertColumn(0, _T("名称"), LVCFMT_IMAGE|LVCFMT_LEFT); m_ctlUserList.InsertColumn(1, _T("密码"), LVCFMT_CENTER); m_ctlUserList.InsertColumn(2, _T("地址"), LVCFMT_CENTER); m_ctlUserList.InsertColumn(3, _T("端口"), LVCFMT_CENTER); m_ctlUserList.InsertColumn(4, _T("时间"), LVCFMT_CENTER); //设置各列的宽度 CRect rect; m_ctlUserList.GetClientRect(&rect);//获取列表视图控件的宽度 int nWidth = rect.Width(); m_ctlUserList.SetColumnWidth(0, nWidth * 25 / 100);//名称占25% m_ctlUserList.SetColumnWidth(1, nWidth * 13 / 100);//密码占13% m_ctlUserList.SetColumnWidth(2, nWidth * 25 / 100);//地址占25% m_ctlUserList.SetColumnWidth(3, nWidth * 12 / 100);//端口占12% m_ctlUserList.SetColumnWidth(4, nWidth * 25 / 100);//时间占25% } /* * 初始化用户列表 */ void CServerDlg::InitUserList(void) { LoadUserList(m_UserList);//读取用户信息 //遍历链表的每个节点,读取数据,初始化用户列表 POSITION pos; int nLine = 0; for (pos = m_UserList.GetHeadPosition(); NULL != pos;) { CUserInfo *pUserInfo = (CUserInfo*)m_UserList.GetNext(pos); if (NULL != pUserInfo) { m_ctlUserList.InsertItem(nLine,pUserInfo->m_strName,1); //名称,用户初始化为离线状态 m_ctlUserList.SetItemText(nLine,1,pUserInfo->m_strPassword); //密码 in_addr userAddr; userAddr.S_un.S_addr = (long)pUserInfo->m_lIP; CString strUserAddr(inet_ntoa(userAddr)); //IP m_ctlUserList.SetItemText(nLine,2,strUserAddr); CString strUserPort; //端口 strUserPort.Format("%d",ntohs(pUserInfo->m_nPort)); m_ctlUserList.SetItemText(nLine,3,strUserPort); CString strUserTime = pUserInfo->m_time.Format("%c"); //端口 m_ctlUserList.SetItemText(nLine,4,strUserTime); nLine++; } } } /* * 保存用户信息 */ void CServerDlg::SaveUserList(CObList &obList) { char appPath[256]; GetCurrentDirectory(256,appPath); //取得应用程序当前路径 CString filePath; //保存Ini文件名 filePath.Format("%s",appPath); filePath +="\\"; filePath += USERLISTINI; //删除原来的文件 DeleteFile(filePath); POSITION pos; int nIndex = 0; //遍历整个用户链表 for(pos = obList.GetHeadPosition(); pos != NULL; ) { //获取数据 CUserInfo *pUserInfo = (CUserInfo*)obList.GetNext(pos);//用户信息 if (NULL == pUserInfo) { break; } CString strSection("section"); //section CString strIndex; strIndex.Format("%d",nIndex); strSection += strIndex; in_addr userAddr; userAddr.S_un.S_addr = (long)pUserInfo->m_lIP; CString strUserAddr(inet_ntoa(userAddr)); //用户IP CString strUserPort; //用户端口 strUserPort.Format("%d",pUserInfo->m_nPort); CString strUserTime; //用户登录线时间 strUserTime.Format("%ld", (long)pUserInfo->m_time.GetTime()); //写用户名字 WritePrivateProfileString(strSection, _T("Name"), pUserInfo->m_strName, filePath); //写用户密码 WritePrivateProfileString(strSection, _T("Password"), pUserInfo->m_strPassword, filePath); //写用户地址 WritePrivateProfileString(strSection, _T("Address"), strUserAddr,filePath); //写用户端口 WritePrivateProfileString(strSection, _T("Port"), strUserPort,filePath); //写用时间 WritePrivateProfileString(strSection, _T("Time"), strUserTime,filePath); delete pUserInfo;//删除对象 pUserInfo = NULL; nIndex++; } obList.RemoveAll();//删除链表所有节点 } /* * 读取用户信息 */ void CServerDlg::LoadUserList(CObList &obList) { #define TEMP_BUF_SIZE 32//缓冲区长度 char appPath[256]; GetCurrentDirectory(256,appPath); //取得应用程序当前路径 CString filePath; //保存Ini文件名 filePath.Format("%s",appPath); filePath += "\\"; filePath += USERLISTINI; int nIndex = 0; while (TRUE) { CString strSection("section"); CString strIndex; strIndex.Format("%d",nIndex); strSection += strIndex; //用户名称 CString strSectionKey = "Name"; CString strValue = _T(""); char cBuf[TEMP_BUF_SIZE]; memset(cBuf, 0, TEMP_BUF_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } CUserInfo *pUserInfo = new CUserInfo();//新建CUserInfo对象 pUserInfo->m_strName = cBuf; //读取用户密码 strSectionKey = "Password"; memset(cBuf, 0, TEMP_BUF_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } pUserInfo->m_strPassword = cBuf; //读取用户地址 strSectionKey = "Address"; memset(cBuf, 0, TEMP_BUF_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } u_long clinetAddr = inet_addr(cBuf); pUserInfo->m_lIP = (DWORD)clinetAddr; //读取用户端口 strSectionKey = "Port"; memset(cBuf, 0, TEMP_BUF_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } pUserInfo->m_nPort = atoi(cBuf); //读取用户时间 strSectionKey = "Time"; memset(cBuf, 0, TEMP_BUF_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } time_t time = atol(cBuf); pUserInfo->m_time = time; obList.AddTail(pUserInfo); //加入链表 nIndex++; } } /* * 保存离线消息 */ void CServerDlg::SaveOfflineMsg(CObList &obList) { char appPath[256]; GetCurrentDirectory(256,appPath); //取得应用程序当前路径 CString filePath; //保存Ini文件名 filePath.Format("%s",appPath); filePath +="\\"; filePath += OFFLINEMSGLIST; //删除原来的文件 DeleteFile(filePath); POSITION pos; int nIndex = 0; for(pos = obList.GetHeadPosition(); pos != NULL; ) { CChatPacket *pPacket = (CChatPacket*)obList.GetNext(pos);//用户信息 if (NULL == pPacket) { break; } CString strSection("section"); //section CString strIndex; strIndex.Format("%d",nIndex); strSection += strIndex; CString strTime; strTime.Format("%ld",(long)pPacket->m_time.GetTime()); pPacket->m_strMsg.Replace("\r\n", "$");//取代回车符为$ //写发送消息的用户名称 WritePrivateProfileString(strSection, _T("SendMsgUser"), pPacket->m_UserInfo.m_strName, filePath); //发送消息用户 //写接收消息的用户名称 WritePrivateProfileString(strSection, _T("RecvMsgUser"), pPacket->m_OfflineUserInfo.m_strName, filePath); //接收消息用户 //写发送消息 的时间 WritePrivateProfileString(strSection, _T("Time"), strTime,filePath); //发送消息时间 //写发送的消息 WritePrivateProfileString(strSection, _T("Message"), pPacket->m_strMsg, filePath); //发送的消息 delete pPacket; pPacket = NULL; nIndex++; } obList.RemoveAll(); } /* * 读取离线消息 */ void CServerDlg::LoadOfflineMsg(CObList &obList) { m_csOfflineList.Lock(); char appPath[256]; GetCurrentDirectory(256,appPath); //取得应用程序当前路径 CString filePath; //保存Ini文件名 filePath.Format("%s",appPath); filePath += "\\"; filePath += OFFLINEMSGLIST; int nIndex = 0; while (TRUE) { CString strSection("section"); //section CString strIndex; strIndex.Format("%d",nIndex); strSection += strIndex; //读取发送消息的用户名称 CString strSectionKey = "SendMsgUser"; CString strValue = _T(""); char cBuf[MAX_MSG_SIZE]; memset(cBuf, 0, MAX_MSG_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } CChatPacket *pPacket = new CChatPacket(); //新建CChatPacket对象 pPacket->m_type = CChatPacket::MESSAGE; pPacket->m_UserInfo.m_strName = cBuf; //发送消息的用户名 //读取接收消息的用户名称 strSectionKey = "RecvMsgUser"; memset(cBuf, 0, MAX_MSG_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } pPacket->m_OfflineUserInfo.m_strName = cBuf; //读取发送消息时间 strSectionKey = "Time"; memset(cBuf, 0, MAX_MSG_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } time_t time = atol(cBuf); pPacket->m_time = time; //读取发送消息 strSectionKey = "Message"; memset(cBuf, 0, MAX_MSG_SIZE); if(0 == GetPrivateProfileString (strSection, strSectionKey, NULL, cBuf, TEMP_BUF_SIZE, filePath)) { break; } ////取代$为回车符 CString strMsg(cBuf); strMsg.Replace( "$","\r\n"); pPacket->m_strMsg = strMsg; obList.AddTail(pPacket);//加入链表 nIndex++; } m_csOfflineList.Unlock(); } /* * 处理数据 */ BOOL CServerDlg::ProcessPendingRead(CArchive *pArchiveIn, CArchive *pArchiveOut, CClientSocket *pClientSocket) { do { CChatPacket chatPact;//接收数据包 chatPact.Serialize(*pArchiveIn); if (CChatPacket::MESSAGE == chatPact.m_type)//发给离线用户的消息 { m_csOfflineList.Lock(); //保存离线用户消息 CChatPacket *pChatPacket = new CChatPacket(); //包类型 pChatPacket->m_type = CChatPacket::MESSAGE; //发送消息用户 pChatPacket->m_UserInfo.m_strName = chatPact.m_UserInfo.m_strName; //接收消息用户 pChatPacket->m_OfflineUserInfo.m_strName = chatPact.m_OfflineUserInfo.m_strName; //发送的消息 pChatPacket->m_strMsg = chatPact.m_strMsg; //发包时间 pChatPacket->m_time = chatPact.m_time; //加入离线消息链表 m_OfflineMsgList.AddTail(pChatPacket); m_csOfflineList.Unlock(); }else if (CChatPacket::USERLIST == chatPact.m_type)//请求用户列表--用户刚登录 { //保存用户信息 pClientSocket->SaveUserInfo(chatPact.m_UserInfo); //户更新信息 if (!UpdateUserList(chatPact.m_UserInfo, /*pArchiveOut,*/ pClientSocket)) return FALSE; //向所有的在线用户发送用户列表 SendUserList(); //转发离线消息 TransmitMsg(chatPact, /*pArchiveOut*/pClientSocket); //更新服务器界面 UpdateServerListCtl(m_UserList); } } while(!pArchiveIn->IsBufferEmpty()); return TRUE; } /* * 发送用户列表 */ void CServerDlg::SendUserList() { //复制用户链表 CObList tempChatterlist; CopyUserList(tempChatterlist); CChatPacket packet; packet.m_type = CChatPacket::USERLIST; //包的类型 packet.m_pUserList = &tempChatterlist; //用户链表 m_csChatterList.Lock();//上锁 //向所有在线用户发送列表 POSITION pos = NULL; for (pos = m_ChatterList.GetHeadPosition(); NULL!=pos;) { CClientSocket *pClientSocket = (CClientSocket*)m_ChatterList.GetNext(pos); pClientSocket->SendUserList(&packet);//发送数据包 } m_csChatterList.Unlock();//解锁 DeleteTempUserList(tempChatterlist);//删除临时链表 } /* * 复制用户链表 */ void CServerDlg::CopyUserList(CObList &obList) { if (m_UserList.IsEmpty()) { return ; } POSITION pos = NULL; CUserInfo *pUserInfo = NULL; CUserInfo *pTempUserInfo = NULL; for (pos = m_UserList.GetHeadPosition(); pos != NULL;) { pUserInfo = (CUserInfo*)m_UserList.GetNext(pos); //不要复制用户的密码 pTempUserInfo = new CUserInfo(); pTempUserInfo->m_strName = pUserInfo->m_strName; //名称 pTempUserInfo->m_eStatus = pUserInfo->m_eStatus; //状态 pTempUserInfo->m_lIP = pUserInfo->m_lIP; //IP pTempUserInfo->m_nPort = pUserInfo->m_nPort; //端口 obList.AddTail(pTempUserInfo); } } /* * 删除临时链表 */ void CServerDlg::DeleteTempUserList(CObList &obList) { if (obList.IsEmpty()) { return; } POSITION pos = NULL; CUserInfo *pUserInfo = NULL; for (pos = obList.GetHeadPosition(); NULL != pos;) { pUserInfo = (CUserInfo*)obList.GetNext(pos); delete pUserInfo; pUserInfo = NULL; } obList.RemoveAll(); } /* * 更新用户链表 */ BOOL CServerDlg::UpdateUserList(const CUserInfo &userInfo, CClientSocket *pClientSocket) { BOOL retVal = TRUE; //返回值 m_csUserList.Lock(); //上锁 POSITION pos; //位置变量 CUserInfo *pUserInfo = NULL; //用户对象指针 BOOL bFind = FALSE; //是否找到该用户 //该用户是否存在于链表中 for (pos = m_UserList.GetHeadPosition(); NULL != pos;) { pUserInfo = (CUserInfo*)m_UserList.GetNext(pos);//节点下移 if (pUserInfo->m_strName == userInfo.m_strName )//名字相同 { if (pUserInfo->m_strPassword == userInfo.m_strPassword) //在册用户 { if(CUserInfo::ONLINE == pUserInfo->m_eStatus) //用户已经登录 { //从在线链表中删除该节点 DeleteChatter(pClientSocket); //发送“用户已经登录”消息 CChatPacket packet; packet.m_type = CChatPacket::SERVERMSG; //数据包类型 packet.m_strMsg = _T(" 用户已经登录! ");//消息 packet.m_time = CTime::GetCurrentTime(); //时间 pClientSocket->SendUserMsg(&packet); //发送数据 m_csUserList.Unlock(); //解锁 return FALSE; }else//用户登录 { pUserInfo->m_eStatus = CUserInfo::ONLINE; //修改用户状态 pUserInfo->m_lIP = userInfo.m_lIP; //IP地址 pUserInfo->m_nPort = userInfo.m_nPort; //端口 bFind = TRUE; break; } }else//密码错误 { //从在线链表中删除该节点 DeleteChatter(pClientSocket); //发送“密码错误”消息 CChatPacket packet; packet.m_type = CChatPacket::SERVERMSG; //数据包类型 packet.m_strMsg = _T(" 密码错误\t\n 请重新登录! "); //消息 packet.m_time = CTime::GetCurrentTime(); //时间 pClientSocket->SendUserMsg(&packet);//发送数据 m_csUserList.Unlock();//解锁 return FALSE; } } } if (FALSE == bFind)//注册新用户 { CUserInfo *pUserInfo = new CUserInfo(); pUserInfo->m_strName = userInfo.m_strName; //姓名 pUserInfo->m_strPassword = userInfo.m_strPassword; //密码 pUserInfo->m_eStatus = CUserInfo::ONLINE; //状态 pUserInfo->m_lIP = userInfo.m_lIP; //地址 pUserInfo->m_nPort = userInfo.m_nPort; //端口 pUserInfo->m_time = userInfo.m_time; //时间 m_UserList.AddTail(pUserInfo); //加入链表 } m_csUserList.Unlock();//解锁 return retVal; } /* * 转发离线消息 */ void CServerDlg::TransmitMsg(const CChatPacket &packet, CClientSocket *pClientSocket) { m_csOfflineList.Lock(); POSITION pos1 = NULL; //位置变量 POSITION pos2 = NULL; //位置变量 CChatPacket *pPacket = NULL;//数据包 //遍历整个离线消息链表 for (pos1 = m_OfflineMsgList.GetHeadPosition(); (pos2 = pos1) != NULL;) { //取出数据包 pPacket = (CChatPacket*)m_OfflineMsgList.GetNext(pos1); //登录用户的名字和接收离线消息的用户名字相同 if (pPacket->m_OfflineUserInfo.m_strName == packet.m_UserInfo.m_strName) { pClientSocket->SendUserMsg(pPacket);//发送离线消息 m_OfflineMsgList.RemoveAt(pos2); //删除链表节点 delete pPacket; //删除对象 pPacket = NULL; } } m_csOfflineList.Unlock(); } /* * 更新服务器界面 */ void CServerDlg::UpdateServerListCtl(const CObList &obList) { m_csUserList.Lock();//上锁 //删除原来数据项 m_ctlUserList.DeleteAllItems(); POSITION pos = NULL; //位置变量 int nIndex = 0; //序号 for (pos = m_UserList.GetHeadPosition(); NULL != pos;) { //取出用户信息 CUserInfo *pUserInfo = (CUserInfo*)m_UserList.GetNext(pos); if (CUserInfo::ONLINE == pUserInfo->m_eStatus)//在线状态 { //插入数据项 m_ctlUserList.InsertItem(nIndex, pUserInfo->m_strName,CUserInfo::ONLINE); }else//离线状态 { //插入数据项 m_ctlUserList.InsertItem(nIndex, pUserInfo->m_strName,CUserInfo::OFFLINE); } m_ctlUserList.SetItemText(nIndex,1,pUserInfo->m_strPassword); //用户密码 in_addr userAddr; userAddr.S_un.S_addr = (long)pUserInfo->m_lIP; CString strUserAddr(inet_ntoa(userAddr)); //用户IP m_ctlUserList.SetItemText(nIndex,2,strUserAddr); CString strUserPort; //用户端口 strUserPort.Format("%d",ntohs(pUserInfo->m_nPort)); m_ctlUserList.SetItemText(nIndex,3,strUserPort); CString strUserTime = pUserInfo->m_time.Format("%c"); //登录时间 m_ctlUserList.SetItemText(nIndex,4,strUserTime); nIndex++; } m_csUserList.Unlock();//解锁 } /* * 当用户离线时删除用户 */ void CServerDlg::ReleaseChatter(CClientSocket *pClientSocket) { m_csChatterList.Lock(); POSITION pos = NULL; //找到该用户 if ((pos = m_ChatterList.Find(pClientSocket)) != NULL) { ASSERT((CClientSocket*)m_ChatterList.GetAt(pos) == pClientSocket); //获取该用户信息 CUserInfo userInfo = pClientSocket->GetUserInfo(); //更新该用户信息 POSITION posUser = NULL; for (posUser = m_UserList.GetHeadPosition(); posUser != NULL;) { CUserInfo *pUserInfo = (CUserInfo*)m_UserList.GetNext(posUser); if (pUserInfo->m_strName == userInfo.m_strName) { pUserInfo->m_eStatus = CUserInfo::OFFLINE; //修改状态为离线 pUserInfo->m_lIP = userInfo.m_lIP; //修改用户地址 pUserInfo->m_nPort = userInfo.m_nPort; //修改用户端口 pUserInfo->m_time = CTime::GetCurrentTime();//设置离线时间 break; } } //删除该在线用户 m_ChatterList.RemoveAt(pos); //通知所有在线用户更新用户列表 SendUserList(); //更新服务器界面 UpdateServerListCtl(m_UserList); } m_csChatterList.Unlock(); } /* * 登录失败处理 */ void CServerDlg::DeleteChatter(CClientSocket *pClientSocket) { m_csChatterList.Lock(); POSITION pos = NULL; if ((pos = m_ChatterList.Find(pClientSocket)) != NULL) { ASSERT((CClientSocket*)m_ChatterList.GetAt(pos) == pClientSocket); //删除该在线用户 m_ChatterList.RemoveAt(pos); } m_csChatterList.Unlock(); } /* * WM_DESTROY消息相应函数 */ void CServerDlg::OnDestroy() { SaveUserList(m_UserList); //保存用户信息 SaveOfflineMsg(m_OfflineMsgList); //保存离线信息 DeleteAllChatter(); //删除在线用户 if (NULL != m_pListenSocket) //删除CListenSocket类对象 { delete m_pListenSocket; m_pListenSocket = NULL; } if (NULL != m_pImageList) //删除CImageList类对象 { delete m_pImageList; m_pImageList = NULL; } } /* * 右击列表控件响应函数 */ void CServerDlg::OnRclickClientList(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; if(pNMListView->iItem != -1) { DWORD dwPos = GetMessagePos(); //鼠标获取位置 CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); CMenu menu; VERIFY( menu.LoadMenu(IDR_SERVER_LIST_MENU)); //装载菜单资源 CMenu* popup = menu.GetSubMenu(0); //获取菜单项 ASSERT( popup != NULL ); //弹出快捷菜单 popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this ); } *pResult = 0; } /* * 处理菜单消息 */ void CServerDlg::OnServerListDeleteMenuitem() { //获得被选中数据项的位置 POSITION pos = m_ctlUserList.GetFirstSelectedItemPosition(); int nSelectedItem = m_ctlUserList.GetNextSelectedItem(pos); //获取用户名称 CString strPeerName = m_ctlUserList.GetItemText(nSelectedItem, 0); POSITION pos1 = NULL; //位置变量 POSITION pos2 = NULL; //位置变量 BOOL bDeleteUser = FALSE; //是否找到该用户 //在用户链表中查找 for (pos1 = m_UserList.GetHeadPosition();(pos2=pos1)!= NULL;) { //取出数据 CUserInfo* pUserInfo = (CUserInfo*)m_UserList.GetNext(pos1); if (pUserInfo->m_strName == strPeerName) //名称相同 { if (pUserInfo->m_eStatus == CUserInfo::ONLINE) //不能删除在线用户 { AfxMessageBox("不能删除在线用户!",MB_OK, -1); return ; }else//删除不在线用户 { CUserInfo *pUserInfo = (CUserInfo*)m_UserList.GetAt(pos2); m_UserList.RemoveAt(pos2); //删除指针 delete pUserInfo; //删除对象 pUserInfo = NULL; bDeleteUser = TRUE; //更新服务器界面 UpdateServerListCtl(m_UserList); } } } if (TRUE == bDeleteUser) { //通知客户端更新成员列表 SendUserList(); } } /* * 删除所有在线用户 */ void CServerDlg::DeleteAllChatter( void ) { POSITION pos; CClientSocket *pClient = NULL; for (pos = m_ChatterList.GetHeadPosition(); NULL != pos; ) { pClient = (CClientSocket*)m_ChatterList.GetNext(pos); delete pClient; pClient = NULL; } m_ChatterList.RemoveAll(); }